﻿// Spun AJAX Framework
// Copyright (C) 2008 Blake Hegerle
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Spun.Communications.Hosting;
using Spun.Applications;
using LitJson;
using System.Net;
using System.IO;
using Spun.Communications.Applications.Services;
using Spun.Utility.Logging;

namespace Spun.Communications.Applications
{
    public abstract class ContextualServer : IServer
    {
        public static string CONTENT_TYPE = "application/json";

        public ContextualServer(ApplicationContextManager ApplicationContextManager)
        {
            this.ApplicationContextManager = ApplicationContextManager;
        }

        public static void DoResponse(HttpListenerContext Context, int StatusCode, ResponseObject ResponseObject)
        {
            var Response = Context.Response;

            Response.ContentType = CONTENT_TYPE;
            Response.StatusCode = StatusCode;

            using (var Writer = new StreamWriter(Response.OutputStream))
                JsonMapper.ToJson(ResponseObject, new JsonWriter(Writer));

            Response.Close();
        }

        protected abstract void ProcessRequest(HttpListenerContext Context, string RelativePath, ApplicationContext ApplicationContext);

        protected virtual string GetRequestBody(HttpListenerContext Context)
        {
            string Body;

            using (var Reader = new StreamReader(Context.Request.InputStream))
                Body = Reader.ReadToEnd();

            if (string.IsNullOrEmpty(Body))
                Body = Context.Request.QueryString[Constants.ACTION_SERVER_QUERY_STRING_ARGUMENT_NAME];

            return Body;
        }

        #region IServer Members

        public void ProcessRequest(HttpListenerContext Context, string RelativePath)
        {
            try
            {
                var CookieName = Constants.Cookies.APPLICATION_TOKEN_COOKIE;
                var Cookie = Context.Request.Cookies[CookieName];

                if (Cookie == null)
                    throw new Exception("Missing authentication cookie " + CookieName);

                var Json = Uri.UnescapeDataString(Cookie.Value);
                var Token = JsonMapper.ToObject<Token>(Json);

                var ApplicationContext = ApplicationContextManager[Token];

                using (new ThreadToApplicationContextAssociation(ApplicationContext))
                    ProcessRequest(Context, RelativePath, ApplicationContext);
            }
            catch (Exception e)
            {
                LoggingComponent.Logger.LogException(LogLevel.Error, e);
                DoResponse(Context, 500, new ResponseObject(e));
            }
        }

        #endregion

        private ApplicationContextManager ApplicationContextManager;
    }
}
